package com.android.tnovoselec.travelassistant.view;

import android.app.Activity;
import android.content.Context;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapView;

public class CustomMapView extends MapView {

	public interface OnZoomLevelChangeLister {
		public void onZoomLevelChanged(int oldZoomLevel, int newZoomLevel);
	}

	public interface OnMapMovedListener {
		public void onMapMoved(GeoPoint tl, GeoPoint br);
	}

	private int oldZoomLevel = 1;
	private GeoPoint tlOld = null;
	private GeoPoint brOld = null;

	private Context mContext;
	private long lastTouchTime = -1;
	private Handler handler = new Handler();
	private OnZoomLevelChangeLister zoomListener;
	private OnMapMovedListener mapMovedListener;
	private final int zoomCheckingDelay = 500;

	public CustomMapView(Context context, AttributeSet attrs) {
		super(context, attrs);
		this.mContext = context;
	}

	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		if (ev.getAction() == MotionEvent.ACTION_DOWN) {
			long thisTime = System.currentTimeMillis();
			if (thisTime - lastTouchTime < 250) {
				getController().zoomInFixing((int) ev.getX(), (int) ev.getY());
				lastTouchTime = -1;
			} else {
				lastTouchTime = thisTime;
			}
		}

		return super.onInterceptTouchEvent(ev);
	}

	public void registerOnZoomLevelChangedListener(OnZoomLevelChangeLister listener) {
		this.zoomListener = listener;
		handler.postDelayed(zoomChecker, zoomCheckingDelay);
	}

	public void unregisterOnZoomChangedListener() {
		handler.removeCallbacks(zoomChecker);
	}

	public void registerOnMapMovedListener(OnMapMovedListener listener) {
		this.mapMovedListener = listener;
		handler.postDelayed(mapChecker, zoomCheckingDelay);
	}

	public void unregisterOnMapMovedListener() {
		handler.removeCallbacks(mapChecker);
	}

	private Runnable zoomChecker = new Runnable() {
		public void run() {
			int currentZoomLevel = getZoomLevel();
			if (currentZoomLevel != oldZoomLevel) {
				zoomListener.onZoomLevelChanged(oldZoomLevel, currentZoomLevel);
			}
			oldZoomLevel = currentZoomLevel;
			handler.removeCallbacks(zoomChecker);
			handler.postDelayed(zoomChecker, zoomCheckingDelay);

		}
	};

	private Runnable mapChecker = new Runnable() {
		public void run() {
			DisplayMetrics metrics = new DisplayMetrics();
			((Activity) mContext).getWindowManager().getDefaultDisplay().getMetrics(metrics);

			GeoPoint tlNew = getProjection().fromPixels(0, 0);
			GeoPoint brNew = getProjection().fromPixels(metrics.widthPixels, metrics.heightPixels);

			if (brOld != null && tlOld != null && !(tlNew.equals(tlOld) && brNew.equals(brOld))) {
				mapMovedListener.onMapMoved(tlNew, brNew);
				Log.i("Map", "maplisteenr fired");
			}

			brOld = brNew;
			tlOld = tlNew;
			handler.postDelayed(mapChecker, zoomCheckingDelay);

		}
	};

	public void disableOnMoveListener() {
		this.brOld = null;
		this.tlOld = null;
	}

	public void animateTo(GeoPoint point) {
		brOld = null;
		tlOld = null;
		handler.removeCallbacks(zoomChecker);
		handler.removeCallbacks(mapChecker);
		this.getController().animateTo(point, resetCoords);
		handler.postDelayed(zoomChecker, zoomCheckingDelay);
		handler.postDelayed(mapChecker, zoomCheckingDelay);
	}

	public void zoomToSpan(int lat, int lng) {
		handler.removeCallbacks(zoomChecker);
		handler.removeCallbacks(mapChecker);
		this.getController().zoomToSpan(lat, lng);
		handler.postDelayed(zoomChecker, zoomCheckingDelay);
		handler.postDelayed(mapChecker, zoomCheckingDelay);
	}

	private Runnable resetCoords = new Runnable() {

		@Override
		public void run() {
			brOld = null;
			tlOld = null;

		}
	};
	public GeoPoint getCurrentMiddlePoint(){
		DisplayMetrics metrics = new DisplayMetrics();
		((Activity) mContext).getWindowManager().getDefaultDisplay().getMetrics(metrics);
		GeoPoint tlNew = getProjection().fromPixels(0, 0);
		GeoPoint brNew = getProjection().fromPixels(metrics.widthPixels, metrics.heightPixels);
		
		return new GeoPoint((tlNew.getLatitudeE6() + brNew.getLatitudeE6())/ 2,
				 (tlNew.getLongitudeE6() + brNew.getLongitudeE6()) / 2);
	}
}
